/**
  ******************************************************************************
  * File Name          : e22.c
  * Description        : This file provides code for the configuration
  *                      of the lora e22-400t22s instances.
  ******************************************************************************
  * @attention
  *
  ******************************************************************************
  */
#include "lora.h"
#include <stdio.h>
#include <string.h>
#include "bsp.h"
#include "tskcfg.h"

#define WHL101_MAX_TMPBFLEN   128

static const LoRa_ConfigParaType LoRa_CfgPara = 
{
	.stinfo = "LoRa Start!",
	.wmode  = ":FP\r\n",
	.pmode  = ":RUN\r\n",
	.spd    = ":1\r\n",
	.fec    = ":ON\r\n",
	.pwr    = ":20\r\n",
	.sendok = ":0\r\n",
};

static char tmpbf[WHL101_MAX_TMPBFLEN];   /* command payload string */

uint8_t LoRa_StartUp(void)
{
	memset(&LoRa_RecvBuf, 0, sizeof(LoRa_BufType));
	memset(&LoRa_RecvIsr, 0, sizeof(LoRa_BufType));
	
  vTaskDelay(100);
  
  xQueueReset(LoRaRecv_qhd);
  
	LoRa_Reload(1);
	LoRa_PwrEn(1);
	LoRa_Reset(1);
		
	if(xQueueReceive(LoRaRecv_qhd, &LoRa_RecvBuf, 30000) == pdTRUE)
	{
		if(strstr((const char*)LoRa_RecvBuf.buf, LoRa_CfgPara.stinfo) != NULL)
		{
			return 0;
		}
		else
		{
			return 1;
		}
	}
	
	return 2;
}

/* multiple instances can be shared */
static uint8_t lora_cmd_process(const WHL101_CommandTyp *cmd, const char *para)
{
  int8_t retry = 0;
  char *p = NULL;

  retry = cmd->rty;

  while(retry-->0)
  {
		xQueueReset(LoRaRecv_qhd);
		memset(&LoRa_RecvBuf, 0, sizeof(LoRa_BufType));
		memset(&LoRa_RecvIsr, 0, sizeof(LoRa_BufType));
		
		/* send cmd */
		if(cmd->cmdtype == LORA_SET_PARA)
		{
			if( (strlen(cmd->cstr) + strlen(para)) > WHL101_MAX_TMPBFLEN-1 )
			{
				return 1;
			}
			strcpy(tmpbf, cmd->cstr);
			strcat(tmpbf, (para+1));
			LoRa_UartSendStr(tmpbf);
		}
		else
		{
			LoRa_UartSendStr(cmd->cstr);
		}
		
		/* waiting for reply */
    while(xQueueReceive(LoRaRecv_qhd, &LoRa_RecvBuf, cmd->timout) == pdTRUE)
    {
			/* empty buffer */
			if(LoRa_RecvBuf.count == 0x00) 
			{
				continue;
			}
			
			p = strstr((const char*)LoRa_RecvBuf.buf, cmd->rstr);
			if( p != NULL )  /* keyword match successful */
			{
				if( (cmd->cmdtype == LORA_SET_PARA) || (cmd->cmdtype == LORA_SIMPLE_INS) )
				{
					return 0;
				}
				
				p = strchr(p, ':');  /* offset to parameter */
				
				if(cmd->cmdtype == LORA_CHECK_PARA)
				{
					if( strstr(p, para) != NULL )
					{
						return 0;
					}
					else /* parameter matching failed, return withont retry */
					{
						return 2;
					}
				}
				
				return 3;
			}
    }
		
		if(retry <= 0)
		{
			return 4;
		}
  }
	
  return 5;
}

uint8_t LoRa_Config(uint16_t netid, uint8_t localid, uint8_t channel)
{
	uint8_t err = 0;
	uint8_t need_rboot = 0;
	uint16_t addr;
	char temp[8];
	
	/* +++ */
	err = lora_cmd_process(&lora_cmd_ppp, NULL);
	if(err != 0) return 1;
	
	/* a */
	err = lora_cmd_process(&lora_cmd_a, NULL);
	if(err != 0) return 2;
	
	/* AT+E */
	err = lora_cmd_process(&lora_cmd_e, NULL);
	if(err != 0) return 3;
	
	/* wmode */
	err = lora_cmd_process(&lora_cmd_check_wmode, LoRa_CfgPara.wmode);
	switch(err)
	{
		case 2:
			need_rboot = 1;
			if(lora_cmd_process(&lora_cmd_set_wmode, LoRa_CfgPara.wmode) != 0)return 4;
			break;
		case 0:
			break;
		default:
			return 5;
	}
	
	/* pmode */
	err = lora_cmd_process(&lora_cmd_check_pmode, LoRa_CfgPara.pmode);
	switch(err)
	{
		case 0:
			break;
		case 2:
			need_rboot = 1;
			if(lora_cmd_process(&lora_cmd_set_pmode, LoRa_CfgPara.pmode) != 0)return 6;
			break;
		default:
			return 7;
	}
	
	/* spd */
	err = lora_cmd_process(&lora_cmd_check_spd, LoRa_CfgPara.spd);
	switch(err)
	{
		case 0:
			break;
		case 2:
			need_rboot = 1;
			if(lora_cmd_process(&lora_cmd_set_spd, LoRa_CfgPara.spd) != 0)return 8;
			break;
		default:
			return 9;
	}
	
	/* fec */
	err = lora_cmd_process(&lora_cmd_check_fec, LoRa_CfgPara.fec);
	switch(err)
	{
		case 0:
			break;
		case 2:
			need_rboot = 1;
			if(lora_cmd_process(&lora_cmd_set_fec, LoRa_CfgPara.fec) != 0)return 10;
			break;
		default:
			return 11;
	}
	
	/* pwr */
	err = lora_cmd_process(&lora_cmd_check_pwr, LoRa_CfgPara.pwr);
	switch(err)
	{
		case 0:
			break;
		case 2:
			need_rboot = 1;
			if(lora_cmd_process(&lora_cmd_set_pwr, LoRa_CfgPara.pwr) != 0)return 12;
			break;
		default:
			return 13;
	}
	
	/* sendok */
	err = lora_cmd_process(&lora_cmd_check_sendok, LoRa_CfgPara.sendok);
	switch(err)
	{
		case 0:
			break;
		case 2:
			need_rboot = 1;
			if(lora_cmd_process(&lora_cmd_set_sendok, LoRa_CfgPara.sendok) != 0)return 14;
			break;
		default:
			return 15;
	}
	
	addr = ((netid << 4)&0xfff0u) + localid;
	snprintf(temp, 8, ":%d\r\n", addr);
	err = lora_cmd_process(&lora_cmd_check_addr, temp);
	switch(err)
	{
		case 0:
			break;
		case 2:
			need_rboot = 1;
			if(lora_cmd_process(&lora_cmd_set_addr, temp) != 0)return 16;
			break;
		default:
			return 17;
	}
	
	snprintf(temp, 8, ":%d\r\n", channel);
	err = lora_cmd_process(&lora_cmd_check_ch, temp);
	switch(err)
	{
		case 0:
			break;
		case 2:
			need_rboot = 1;
			if(lora_cmd_process(&lora_cmd_set_ch, temp) != 0)return 18;
			break;
		default:
			return 19;
	}
	
	if(need_rboot != 0)
	{
		err = lora_cmd_process(&lora_cmd_cfgtf, NULL);
		if(err != 0) return 20;
		
		/* Z */
		if(lora_cmd_process(&lora_cmd_z, NULL) != 0)
		{
			return 21; 
		}
		
		if(xQueueReceive(LoRaRecv_qhd, &LoRa_RecvBuf, 30000) == pdTRUE)
		{
			if(strstr((const char*)LoRa_RecvBuf.buf, LoRa_CfgPara.stinfo) != NULL)
			{
				return 0;
			}
			else
			{
				return 1;
			}
		}
	}
	
	/* ENTM */
	err = lora_cmd_process(&lora_cmd_entm, NULL);
	if(err != 0) return 22;

	return 0;
}
